﻿using System;
using System.IO;

using Spring.Core.IO;
using Spring.Context;

using Yawf.Core.Exceptions;

namespace Yawf.Core.Utils {
	public class ResourceUtils {
		/// <summary>
		/// Private empty constructor, cause this class is just
		/// a utiliyt class that should not be instanciated.
		/// Just call static methods
		/// </summary>
		private ResourceUtils() {
		}

		/// <summary>
		/// Gets an IResource object from a specific location. The 
		/// locationStr parameter is a typical Spring path, eg it can be an 
		/// file://, assembly://, config:// string
		/// </summary>
		/// <param name="locationStr">path to location of resource</param>
		/// <returns>IResource object representing the physical resources</returns>
		public static IResource GetResource(String locationStr){
			Initializer initializer;
			IApplicationContext appContext;
			IResource resource = null;

			// Get context first
			initializer = Initializer.Instance;
			if (initializer == null){
				throw new YawfException("Application has not been initialized correctly, eg Initializer sigleton is not initialized");
			}
			appContext = initializer.SpringContext;

			try{
				// Try get resources via context if context exists
				if (appContext != null) {
					resource = appContext.GetResource(locationStr);
				} else {
					resource = (new ConfigurableResourceLoader()).GetResource(locationStr);
				}
			}catch(Exception e){
				throw new YawfException("Error reading resource " + locationStr + ",Exception " + e, e);
			}
			
			return resource;
		}													// GetResource

		/// <summary>
		/// Gets an FileInfo object from a specific location. The 
		/// locationStr parameter is a typical Spring path, eg it can be only
		/// be a file and it can not be inside config file or in assembly. This
		/// method checks that the resource is really a physical file 
		/// </summary>
		/// <param name="locationStr">path to location of resource</param>
		/// <returns>FileInfo object representing the physical file</returns>
		public static FileInfo GetFileResource(String locationStr) {
			IResource resource;
			FileInfo resFile;
			
			// Get resource first
			resource = GetResource(locationStr);
			if (resource == null || !resource.Exists){
				throw new YawfException("Resource [" + locationStr + "] does not exists");
			}
			
			try{
				resFile = resource.File;
			}catch(IOException e){
				throw new YawfException("Resource [" + locationStr + "] cannot be found", e);
			}
			
			return resFile;
		}									// GetFileResource

		/// <summary>
		/// Checks if a resource exists
		/// </summary>
		/// <param name="locationStr">Location string of resource</param>
		/// <returns>Truye if resource exists, false otherwise</returns>
		public static bool DoResourceExists(String locationStr) {
			IResource resource;

			// Get resource first
			resource = GetResource(locationStr);
			return resource != null && resource.Exists;
		}

		public static void CopyData(Stream inStream,Stream outStream) {
			byte[] tmpData = new byte[32768];
			int bytesRead;

			try {
				while ((bytesRead = inStream.Read(tmpData, 0, tmpData.Length)) > 0) {
					outStream.Write(tmpData, 0, bytesRead);
				}
			} catch (Exception e) {
				throw new YawfException("Error copying streams", e);
			}
		}
	
	}									// Class
}
